多個物件之間存在著一對多的依賴關係,當一個物件發生改變時,所有跟他有關的物件都會被通知且更新。
現實生活中就有許多觀察者模式的案例,例如:訂閱youtuber,發布新影片就會接收到通知;加入Line官方帳號,會接收到優惠訊息...等等。
name | description |
---|---|
Subject | 抽象目標,提供保存觀察者物件的集合以及增加觀察者物件的方法、刪除觀察者物件的方法以及通知所有觀察者的抽象方法。 |
ConcreteSubject | 具體目標,實作抽象目標中的通知方法。具體目標內部發生改變時會通知所有加入的觀察者物件。 |
Observer | 抽象觀察者,可以是抽象類別或是介面。含有更新自己的抽象方法。 |
ConcreteObserver | 實作抽象觀察者,在目標更改狀態時接收通知並更改自身狀態。 |
就拿現在很紅的Youtuber來做範例,Peeta葛格是一個Youtuber,我們訂閱了之後,就可以接收到他發片的通知,所以Peeta是目標,而我們是觀察者。廠商也訂閱了Peeta,他想知道Peeta發片時是不是葉配影片,所以廠商也是觀察者。
import java.util.*;
enum Type { // 建立列舉方便等等程式使用
BUSINESS, VLOG
}
//抽象目標:分別有存放觀察者的集合以及增加、刪除、通知觀察者的方法
abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>();
//增加觀察者
public void add(Observer observer) {
observers.add(observer);
}
//刪除觀察者
public void remove(Observer observer) {
observers.remove(observer);
}
public abstract void notifyObserver(Type type); //通知觀察者
}
//實體目標 Peeta葛格:實作抽象目標,通知觀察者的方法。
class YoutuberPeeta extends Subject {
public void notifyObserver(Type type) {
String videoType = null;
switch(type){
case BUSINESS:
videoType = "葉配";
break;
case VLOG:
videoType = "vlog";
break;
}
System.out.println("Peeta 發布新" + videoType + "影片");
System.out.println("--------------");
for(Object obs:observers) {
((Observer)obs).response(type);
}
}
}
//抽象觀察者:定義接收到目標時的方法。
interface Observer {
void response(Type type); //反應
}
//實體觀察者 粉絲
class Fans implements Observer {
public void response(Type type) {
switch(type){
case BUSINESS:
System.out.println("紛絲看到葉配表示傷心!");
break;
case VLOG:
System.out.println("紛絲看到VLOG覺得有趣!");
break;
}
}
}
//實體觀察者:廠商
class Vendor implements Observer {
public void response(Type type) {
switch(type){
case BUSINESS:
System.out.println("廠商看到葉配覺得開心!");
break;
case VLOG:
System.out.println("廠商看到VLOG表示為啥不是葉配!");
break;
}
}
}
// Client分別建立目標及兩個觀察者,而目標在發布新影片時會同時通知兩個觀察者
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new YoutuberPeeta();
Observer obs1 = new Fans();
Observer obs2 = new Vendor();
subject.add(obs1);
subject.add(obs2);
subject.notifyObserver(Type.BUSINESS);
System.out.println();
subject.notifyObserver(Type.VLOG);
}
}
output
Peeta 發布新葉配影片
--------------
紛絲看到葉配表示傷心!
廠商看到葉配覺得開心!
Peeta 發布新vlog影片
--------------
紛絲看到VLOG覺得有趣!
廠商看到VLOG表示為啥不是葉配!
多個物件之間存在著一對多的依賴關係,當一個物件發生改變時,所有跟他有關的物件都會被通知且更新。
Subject:抽象目標,提供保存觀察者物件的集合以及增加觀察者物件的方法、刪除觀察者物件的方法以及通知所有觀察者的抽象方法。
ConcreteSubject:具體目標,實作抽象目標中的通知方法。具體目標內部發生改變時會通知所有加入的觀察者物件。
Observer:抽象觀察者,可以是抽象類別或是介面。含有更新自己的抽象方法。
ConcreteObserver:實作抽象觀察者,在目標更改狀態時接收通知並更改自身狀態。
優點
1. 降低目標與觀察者間的耦合關係,兩者之間為抽象耦合關係。
2. 目標與觀察者間建立了一套觸發機制。
缺點
1. 目標與觀察者間的依賴並無完全切除。
2. 當觀察者物件多時,會影響效能。
1. 物件之間存在一對多的關係,一個物件狀態改變會影響其他物件時。